public interface TimeService {
public String getTime();
}
In contrast to Gin, the Errai IOC container does not provide a programmatic way of creating and configuring injectors. Instead, container-level binding rules are defined by implementing a Provider, which is scanned for and auto-discovered by the container.
A Provider is essentially a factory which produces type instances within in the container, and defers instantiation responsibility for the provided type to the provider implementation. Top-level providers use the standard javax.inject.Provider<T> interface.
Types made available as top-level providers will be available for injection in any managed component within the container.
Out of the box, Errai IOC implements these default top-level providers, all defined in the org.jboss.errai.ioc.client.api.builtin package:
CallerProvider : Makes RPC Caller<T> objects available for injection.
DisposerProvider : Makes Errai IoC Disposer<T> objects available for injection.
InitBallotProvider : Makes instances of InitBallot available for injection.
IOCBeanManagerProvider : Makes Errai's client-side bean manager, ClientBeanManager, available for injection.
MessageBusProvider : Makes Errai's client-side MessageBus singleton available for injection.
RequestDispatcherProvider : Makes an instance of the RequestDispatcher available for injection.
RootPanelProvider : Makes GWT's RootPanel singleton injectable.
SenderProvider : Makes MessageBus Sender<T> objects available for injection.
Implementing a Provider is relatively straight-forward. Consider the following two classes:
TimeService.java
public interface TimeService {
public String getTime();
}
TimeServiceProvider.java
@IOCProvider
@Singleton
public class TimeServiceProvider implements Provider<TimeService> {
@Override
public TimeService get() {
return new TimeService() {
public String getTime() {
return "It's midnight somewhere!";
}
};
}
}
If you are familiar with Guice, this is semantically identical to configuring an injector like so:
Guice.createInjector(new AbstractModule() {
public void configure() {
bind(TimeService.class).toProvider(TimeServiceProvider.class);
}
}).getInstance(MyApp.class);
As shown in the above example code, the annotation @IOCProvider is used to denote top-level providers.
The classpath will be searched for all annotated providers at compile time.
Top-level providers are regular beans, so they can inject dependencies–particularly from other top-level providers–as necessary.